/*
 * UpdatePathsDialog.java
 *
 * Created on 15 April 2007, 18:28
 */

package org.cardcopier.ui;

import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import javax.swing.JFileChooser;
import javax.swing.JTextField;
import org.cardcopier.file.ByteSizeFormatter;
import org.cardcopier.file.FileLocation;
import org.cardcopier.file.FileLocationFactory;
import org.cardcopier.file.FileUtils;

/**
 *
 * @author  Mark
 */
public class UpdatePathsDialog extends javax.swing.JDialog {

    public static final int OK = 0;
    public static final int CANCEL = 1;
    
    private final FileLocationFactory fileLocationFactory;
    private final JFileChooser dirChooser;
    private final FileUtils fileUtils = new FileUtils();
    private final ByteSizeFormatter byteSizeFormatter = new ByteSizeFormatter();
    
    private int userChoice = CANCEL;
    private FileLocation sourceDir;
    private File destinationDir;
    
    /** Creates new form UpdatePathsDialog */
    public UpdatePathsDialog(java.awt.Frame parent, boolean modal, FileLocationFactory fileLocationFactory) {
        super(parent, modal);
        this.fileLocationFactory = fileLocationFactory;
        initComponents();

        dirChooser = new JFileChooser();
        dirChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
    }
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
    private void initComponents() {
        jPanel1 = new javax.swing.JPanel();
        eventLabel = new javax.swing.JLabel();
        sourceDirLabel = new javax.swing.JLabel();
        destinationDirLabel = new javax.swing.JLabel();
        eventTextField = new javax.swing.JTextField();
        sourceDirTextField = new javax.swing.JTextField();
        destinationDirTextField = new javax.swing.JTextField();
        chooseSourceDirButton = new javax.swing.JButton();
        chooseDestinationDirButton = new javax.swing.JButton();
        eventDateLabel = new javax.swing.JLabel();
        eventDateChooser = new com.toedter.calendar.JDateChooser();
        sourceSizeLabel = new javax.swing.JLabel();
        destinationSpaceAvailable = new javax.swing.JLabel();
        cancelButton = new javax.swing.JButton();
        okButton = new javax.swing.JButton();
        errorTextField = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Update Paths"));
        eventLabel.setText("Event:");

        sourceDirLabel.setText("Source:");

        destinationDirLabel.setText("Destination:");

        eventTextField.setText("Event");

        sourceDirTextField.setEditable(false);
        sourceDirTextField.setText("Choose a directory");

        destinationDirTextField.setEditable(false);
        destinationDirTextField.setText("Choose a directory");

        chooseSourceDirButton.setText("...");
        chooseSourceDirButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                chooseSourceDirButtonActionPerformed(evt);
            }
        });
        chooseSourceDirButton.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                chooseSourceDirButtonFocusGained(evt);
            }
        });

        chooseDestinationDirButton.setText("...");
        chooseDestinationDirButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                chooseDestinationDirButtonActionPerformed(evt);
            }
        });
        chooseDestinationDirButton.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                chooseDestinationDirButtonFocusGained(evt);
            }
        });

        eventDateLabel.setText("Event Date:");

        sourceSizeLabel.setText("directory size");

        destinationSpaceAvailable.setText("space available");

        org.jdesktop.layout.GroupLayout jPanel1Layout = new org.jdesktop.layout.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(org.jdesktop.layout.GroupLayout.TRAILING, jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(destinationDirLabel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .add(eventDateLabel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .add(sourceDirLabel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 58, Short.MAX_VALUE)
                    .add(eventLabel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 58, Short.MAX_VALUE))
                .add(4, 4, 4)
                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(jPanel1Layout.createSequentialGroup()
                        .add(10, 10, 10)
                        .add(sourceSizeLabel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 346, Short.MAX_VALUE))
                    .add(eventDateChooser, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 119, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(jPanel1Layout.createSequentialGroup()
                        .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                            .add(org.jdesktop.layout.GroupLayout.LEADING, eventTextField, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 327, Short.MAX_VALUE)
                            .add(org.jdesktop.layout.GroupLayout.LEADING, sourceDirTextField, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 327, Short.MAX_VALUE)
                            .add(org.jdesktop.layout.GroupLayout.LEADING, jPanel1Layout.createSequentialGroup()
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                    .add(jPanel1Layout.createSequentialGroup()
                                        .add(10, 10, 10)
                                        .add(destinationSpaceAvailable, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 317, Short.MAX_VALUE))
                                    .add(destinationDirTextField, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 327, Short.MAX_VALUE))))
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                            .add(chooseSourceDirButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 23, Short.MAX_VALUE)
                            .add(jPanel1Layout.createSequentialGroup()
                                .add(chooseDestinationDirButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 23, Short.MAX_VALUE)
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)))))
                .addContainerGap())
        );

        jPanel1Layout.linkSize(new java.awt.Component[] {chooseDestinationDirButton, chooseSourceDirButton}, org.jdesktop.layout.GroupLayout.HORIZONTAL);

        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(jPanel1Layout.createSequentialGroup()
                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(chooseSourceDirButton)
                    .add(sourceDirTextField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(sourceDirLabel))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(sourceSizeLabel)
                .add(11, 11, 11)
                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(destinationDirLabel)
                    .add(chooseDestinationDirButton)
                    .add(destinationDirTextField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(destinationSpaceAvailable)
                .add(14, 14, 14)
                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(eventTextField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(eventLabel))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                    .add(eventDateChooser, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(eventDateLabel))
                .add(22, 22, 22))
        );

        cancelButton.setText("Cancel");
        cancelButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cancelButtonActionPerformed(evt);
            }
        });

        okButton.setText("OK");
        okButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                okButtonActionPerformed(evt);
            }
        });

        errorTextField.setFont(new java.awt.Font("Tahoma", 1, 11));
        errorTextField.setForeground(new java.awt.Color(255, 51, 51));
        errorTextField.setText("errorText");

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(layout.createSequentialGroup()
                        .addContainerGap()
                        .add(jPanel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                    .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
                        .add(20, 20, 20)
                        .add(errorTextField, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 322, Short.MAX_VALUE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(okButton)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(cancelButton)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .add(jPanel1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 207, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(okButton)
                    .add(cancelButton)
                    .add(errorTextField))
                .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void chooseDestinationDirButtonFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_chooseDestinationDirButtonFocusGained
        fieldsValid();
    }//GEN-LAST:event_chooseDestinationDirButtonFocusGained

    private void chooseSourceDirButtonFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_chooseSourceDirButtonFocusGained
        fieldsValid();
    }//GEN-LAST:event_chooseSourceDirButtonFocusGained

    private void chooseDestinationDirButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chooseDestinationDirButtonActionPerformed
        setDestinationDirectory(chooseDir(destinationDir));
    }//GEN-LAST:event_chooseDestinationDirButtonActionPerformed

    private void chooseSourceDirButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chooseSourceDirButtonActionPerformed
        File currentDir = sourceDir.getDirectory();
        File newSourceDir = chooseDir(currentDir);
        if (!newSourceDir.equals(currentDir)) {
            setSourceDirectory(fileLocationFactory.createFileLocation(newSourceDir));
            guessEventDate();
        }        
    }//GEN-LAST:event_chooseSourceDirButtonActionPerformed

    public void setVisible(boolean b) {
        fieldsValid();
        super.setVisible(b);
    }

    public void guessEventDate() {
        Date earliestFileModifiedDate = sourceDir.getEarliestFileDate();
        if (earliestFileModifiedDate != null) {
            eventDateChooser.setDate(earliestFileModifiedDate);
        } else {
            eventDateChooser.setDate(new Date());
        }
    }
    
    private File chooseDir(File currentDir) {
        // If I do not use the absolute file, then the file chooser does something weird
        // where it cd's to the correct dir, but only has the relative path showing, so
        // the resulting dir is a weird hybrid...
        dirChooser.setCurrentDirectory(currentDir.getAbsoluteFile());
        int option = dirChooser.showDialog(this, "Select");
        File newDir = currentDir;
        if (option == JFileChooser.APPROVE_OPTION) {
            newDir = dirChooser.getSelectedFile();
        }
        return newDir;
    }
    
    private void updateDirTextField(File dir, JTextField textField) {
        String dirText = (dir != null ? dir.getAbsolutePath() : "Choose a directory");
        textField.setText(dirText);
    }
    
    private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
        userChoice = CANCEL;
        setVisible(false);
    }//GEN-LAST:event_cancelButtonActionPerformed

    private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
        if (fieldsValid()) {
            userChoice = OK;
            setVisible(false);
        }
    }//GEN-LAST:event_okButtonActionPerformed
    
    private boolean fieldsValid() {
        String error = null;
        if (sourceDir == null) {
            error = "Please choose a source directory";
        } else if (!sourceDir.getDirectory().exists()) {
            error = "Source directory does not exist";
        } else if (sourceDir.getFiles().size() == 0) {
            error = "Source directory does not contain any photos";
        } else if (destinationDir == null) {
            error = "Please choose a destination directory";
        } else if (eventTextField.getText() == null || eventTextField.getText().trim().length() == 0) {
            error = "Please enter an event label";
        } else if (eventDateChooser.getDate() == null) {
            error = "Please choose an event date";
        }
        errorTextField.setText(error);
        return error == null;
    }

    public String getEvent() {
        return eventTextField.getText();
    }

    public void setEvent(String event) {
        eventTextField.setText(event);
    }
    
    public Date getEventDate() {
        return eventDateChooser.getDate();
    }
    
    public void setEventDate(Date eventDate) {
        eventDateChooser.setDate(eventDate);
    }
    
    public FileLocation getSourceDirectory() {
        return sourceDir;
    }
    
    public void setSourceDirectory(FileLocation sourceDir) {
        this.sourceDir = sourceDir;
        updateDirTextField(sourceDir.getDirectory(), sourceDirTextField);
        String spaceNeeded;
        try {
            spaceNeeded = byteSizeFormatter.format(fileUtils.spaceUsedInBytes(sourceDir));
        } catch(IllegalArgumentException e) {
            spaceNeeded = "Size Unknown";
        }
        this.sourceSizeLabel.setText(spaceNeeded);
        
    }
            
    public File getDestinationDirectory() {
        return destinationDir;
    }
    
    public void setDestinationDirectory(File destinationDir) {
        this.destinationDir = destinationDir;
        updateDirTextField(destinationDir, destinationDirTextField);
        String spaceAvailable;
        try {
            spaceAvailable = byteSizeFormatter.format(fileUtils.spaceAvailableInBytes(destinationDir));
        } catch (IOException ex) {
            spaceAvailable = "Unknown Space Available";
        }
        this.destinationSpaceAvailable.setText(spaceAvailable);
    }
    
    public boolean userChoseOk() {
        return userChoice == OK;
    }
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton cancelButton;
    private javax.swing.JButton chooseDestinationDirButton;
    private javax.swing.JButton chooseSourceDirButton;
    private javax.swing.JLabel destinationDirLabel;
    private javax.swing.JTextField destinationDirTextField;
    private javax.swing.JLabel destinationSpaceAvailable;
    private javax.swing.JLabel errorTextField;
    private com.toedter.calendar.JDateChooser eventDateChooser;
    private javax.swing.JLabel eventDateLabel;
    private javax.swing.JLabel eventLabel;
    private javax.swing.JTextField eventTextField;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JButton okButton;
    private javax.swing.JLabel sourceDirLabel;
    private javax.swing.JTextField sourceDirTextField;
    private javax.swing.JLabel sourceSizeLabel;
    // End of variables declaration//GEN-END:variables
    
}
